import cv2
import mediapipe as mp
import numpy as np

# 初始化 MediaPipe FaceMesh
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
    max_num_faces=2,
    refine_landmarks=True,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

# 读取眼镜 PNG（带透明通道）
glasses = cv2.imread("glass.png", cv2.IMREAD_UNCHANGED)

# 打开摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080)
while cap.isOpened():
    success, frame = cap.read()
    if not success:
        print("⚠️ 无法读取摄像头画面")
        break

    # 转换颜色 BGR → RGB
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(rgb_frame)

    if results.multi_face_landmarks:
        for face_landmarks in results.multi_face_landmarks:
            h, w, _ = frame.shape

            # 取左右眼角点 (33 左眼，263 右眼)
            left_eye = face_landmarks.landmark[33]
            right_eye = face_landmarks.landmark[263]

            lx, ly = int(left_eye.x * w), int(left_eye.y * h)
            rx, ry = int(right_eye.x * w), int(right_eye.y * h)

            # 眼镜宽度 = 两眼之间的距离 * 系数（放大点）
            eye_width = int(((rx - lx) ** 2 + (ry - ly) ** 2) ** 0.5 * 2.0)

            # 根据宽度缩放眼镜
            scale_factor = eye_width / glasses.shape[1]
            new_h = int(glasses.shape[0] * scale_factor)
            new_w = eye_width
            resized_glasses = cv2.resize(glasses, (new_w, new_h))

            # 计算眼镜位置（放在双眼中点上方一点）
            cx, cy = (lx + rx) // 2, (ly + ry) // 2
            x1 = cx - new_w // 2
            y1 = cy - new_h // 2
            x2, y2 = x1 + new_w, y1 + new_h

            # 边界检查
            if x1 < 0: x1 = 0
            if y1 < 0: y1 = 0
            if x2 > w: x2 = w
            if y2 > h: y2 = h

            # 取 ROI 区域
            roi = frame[y1:y2, x1:x2]

            # 确保尺寸一致
            gh, gw, _ = resized_glasses.shape
            roi = roi[:gh, :gw]

            # 分离 RGBA
            overlay_rgb = resized_glasses[:, :, :3]
            overlay_alpha = resized_glasses[:, :, 3] / 255.0
            overlay_alpha = overlay_alpha[..., None]

            # 融合
            roi[:] = (overlay_alpha * overlay_rgb + (1 - overlay_alpha) * roi).astype(np.uint8)

    # 显示结果
    cv2.imshow("Virtual Glasses", frame)

    # 按 ESC 退出
    if cv2.waitKey(5) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()